﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DienLib
{
    public class SendKeys
    {
        const int MAX_SK_LEN = 20; // 
        enum Special_Keys
        {
            SK_None,
            SK_ShiftLock,
            SK_ShiftUnlock,
            SK_CtrlLock,
            SK_CtrlUnlock,
            SK_AltLock,
            SK_AltUnlock,
            SK_Delay,
            SK_StartRepeat,
            SK_EndRepeat
        };

        enum Key_Action
        {
            Action_KeyDown,
            Action_KeyUp,
            Action_KeyPress
        };

        enum KeyType
        {
            Key_NotFound,
            Key_Ignore,
            Key_Normal,
            Key_Alt,
            Key_Ctrl,
            Key_Shift,
            Key_CtrlAlt,
            Key_CtrlShift,
            Key_AltShift,
            Key_CtrlAltShift,
            Key_StartRepeat,
            Key_Delay
        };

        struct KeyStruct
        {
            public WINMSG Vk;
            public uint nScan;
            public Key_Action nAction;
            public Special_Keys nSpecial;
            public int nOptional;
        }

        //int GetKeyParam(string Source, string Dest, int Start);

        //KeyType GetNextSpecialKey(string Key, KeyStruct sKey);
        //void ParseKeys();
        //bool SendSingleKey(KeyStruct key, IntPtr wHnd, bool CtrlLocked, bool AltLocked, bool ShiftLocked);

        List<KeyStruct> m_KeyList;

        public static bool Send()
        {

            return true; // If success at last return true
        }

        public static bool SendWait()
        {

            return true; // If success at last return true
        }

        #region ParseKey
        // Parses the keys in m_sKeys string and puts them into m_KeyList
        /*void ParseKeys()
        {
	KeyStruct	tempKey, keyAltHold, keyCtrlHold, keyShiftHold,
				keyAltRelease, keyCtrlRelease, keyShiftRelease;

	keyAltHold.nAction = Key_Action.Action_KeyDown;
	keyAltHold.nOptional = 0;
	keyAltHold.nSpecial = Special_Keys.SK_None;
	keyAltHold.Vk = WINMSG.VK_MENU;
	keyAltHold.nScan = WinAPI.MapVirtualKey((uint)WINMSG.VK_MENU, 0);

	keyCtrlHold.nAction = Key_Action.Action_KeyDown;
	keyCtrlHold.nOptional = 0;
	keyCtrlHold.nSpecial = Special_Keys.SK_None;
	keyCtrlHold.Vk = WINMSG.VK_CONTROL;
	keyCtrlHold.nScan = WinAPI.MapVirtualKey ((uint)WINMSG.VK_CONTROL, 0);

	keyShiftHold.nAction = Key_Action.Action_KeyDown;
	keyShiftHold.nOptional = 0;
	keyShiftHold.nSpecial = Special_Keys.SK_None;
	keyShiftHold.Vk = WINMSG.VK_SHIFT;
	keyShiftHold.nScan = WinAPI.MapVirtualKey ((uint)WINMSG.VK_SHIFT, 0);

	keyAltRelease.nAction = Key_Action.Action_KeyUp;
	keyAltRelease.nOptional = 0;
	keyAltRelease.nSpecial = Special_Keys.SK_None;
	keyAltRelease.Vk = WINMSG.VK_MENU;
	keyAltRelease.nScan = WinAPI.MapVirtualKey ((uint)WINMSG.VK_MENU, 0);

	keyCtrlRelease.nAction = Key_Action.Action_KeyUp;
	keyCtrlRelease.nOptional = 0;
	keyCtrlRelease.nSpecial = Special_Keys.SK_None;
	keyCtrlRelease.Vk = WINMSG.VK_CONTROL;
	keyCtrlRelease.nScan = WinAPI.MapVirtualKey ((uint)WINMSG.VK_CONTROL, 0);

	keyShiftRelease.nAction = Key_Action.Action_KeyUp;
	keyShiftRelease.nOptional = 0;
	keyShiftRelease.nSpecial = Special_Keys.SK_None;
	keyShiftRelease.Vk = WINMSG.VK_SHIFT;
	keyShiftRelease.nScan = WinAPI.MapVirtualKey ((uint)WINMSG.VK_SHIFT, 0);

	m_KeyList.Clear();
	int idx = 0;
	int nKeyLength = m_sKeys.GetLength ();
	char c = 0;
	char szTemp [MAX_SK_LEN];
	SHORT nTemp;
	bool bNotASpecialKey = false;
	
	bool bPushAltRelease = false, bPushCtrlRelease = false, bPushShiftRelease = false;

	while (idx < nKeyLength)
	{
		c = m_sKeys.GetAt (idx);
		// if a normal key
		if (bNotASpecialKey || 
			((c != '<') || ((c == '<') && (idx == nKeyLength - 1)))
			)
		{
			bNotASpecialKey = false;
			tempKey.nAction = Action_KeyPress;
			tempKey.nSpecial = SK_None;
			nTemp = VkKeyScan (c);
			tempKey.Vk = LOBYTE (nTemp);
            int nTempState = HIBYTE(nTemp);

			if (nTempState & 0x0001)
				m_KeyList.push_back (keyShiftHold);
			if (nTempState & 0x0002)
				m_KeyList.push_back (keyCtrlHold);
			if (nTempState & 0x0004)
				m_KeyList.push_back (keyAltHold);
			
			tempKey.nScan = MapVirtualKey (tempKey.Vk, 0);
			m_KeyList.push_back (tempKey);

			if (nTempState & 0x0004)
				m_KeyList.push_back (keyAltRelease);
			if (nTempState & 0x0002)
				m_KeyList.push_back (keyCtrlRelease);
			if (nTempState & 0x0001)
				m_KeyList.push_back (keyShiftRelease);

			if (bPushAltRelease)
				m_KeyList.push_back (keyAltRelease);
			if (bPushCtrlRelease)
				m_KeyList.push_back (keyCtrlRelease);
			if (bPushShiftRelease)
				m_KeyList.push_back (keyShiftRelease);
			bPushAltRelease = false;
			bPushCtrlRelease = false;
			bPushShiftRelease = false;

			++ idx;
		}
		// if a special key
		else
		{
			bNotASpecialKey = false;
			int nTempIdx = idx + 1;
			int nOffset = 0;
			while (nTempIdx < nKeyLength && (nTempIdx < nTempIdx + MAX_SK_LEN - 1))
			{
				c = m_sKeys.GetAt (nTempIdx);
				// found the first token
				if (c == ' ' || c == '>')
				{
					++nTempIdx;
					szTemp [nOffset] = '\0';
					KeyType nType = GetNextSpecialKey (szTemp, tempKey);
					if (nType != Key_StartRepeat && nType != Key_Delay)
					{
						if (c == ' ')
						{
							CString sDest;
							int i = GetKeyParam (m_sKeys, sDest, nTempIdx);
							if (i > 0)
                                nTempIdx += i;
							else
							{
								bNotASpecialKey = true;
								break;
							}
						}
					}
					if (nType != Key_NotFound && nType != Key_Normal)
					{
						if (bPushAltRelease)
							m_KeyList.push_back (keyAltRelease);
						if (bPushCtrlRelease)
							m_KeyList.push_back (keyCtrlRelease);
						if (bPushShiftRelease)
							m_KeyList.push_back (keyShiftRelease);
					}
					switch (nType)
					{
					case Key_NotFound:
						bNotASpecialKey = true;
						break;
					case Key_Ignore:
						bPushAltRelease = false;
						bPushCtrlRelease = false;
						bPushShiftRelease = false;
						break;
					case Key_Normal:
						m_KeyList.push_back (tempKey);
						if (bPushAltRelease)
							m_KeyList.push_back (keyAltRelease);
						if (bPushCtrlRelease)
							m_KeyList.push_back (keyCtrlRelease);
						if (bPushShiftRelease)
							m_KeyList.push_back (keyShiftRelease);
						bPushAltRelease = false;
						bPushCtrlRelease = false;
						bPushShiftRelease = false;
						break;
					case Key_Alt:
						m_KeyList.push_back (keyAltHold);

						bPushAltRelease = true;
						bPushCtrlRelease = false;
						bPushShiftRelease = false;
						break;
					case Key_Ctrl:
						m_KeyList.push_back (keyCtrlHold);

						bPushCtrlRelease = true;
						bPushAltRelease = false;
						bPushShiftRelease = false;
						break;
					case Key_Shift:
						m_KeyList.push_back (keyShiftHold);
						bPushShiftRelease = true;
						bPushAltRelease = false;
						bPushCtrlRelease = false;
						break;
					case Key_CtrlAlt:
						m_KeyList.push_back (keyCtrlHold);
						m_KeyList.push_back (keyAltHold);
						bPushShiftRelease = false;
						bPushAltRelease = true;
						bPushCtrlRelease = true;
						break;
					case Key_CtrlShift:
						m_KeyList.push_back (keyCtrlHold);
						m_KeyList.push_back (keyShiftHold);
						bPushShiftRelease = true;
						bPushAltRelease = false;
						bPushCtrlRelease = true;
						break;
					case Key_AltShift:
						m_KeyList.push_back (keyShiftHold);
						m_KeyList.push_back (keyAltHold);
						bPushShiftRelease = true;
						bPushAltRelease = true;
						bPushCtrlRelease = false;
						break;
					case Key_CtrlAltShift:
						m_KeyList.push_back (keyCtrlHold);
						m_KeyList.push_back (keyAltHold);
						m_KeyList.push_back (keyShiftHold);
						bPushShiftRelease = true;
						bPushAltRelease = true;
						bPushCtrlRelease = true;
						break;
					case Key_StartRepeat:
						if (c == '>')
							tempKey.nOptional = 0;
						else
						{
							CString sDest;
							nTempIdx += GetKeyParam (m_sKeys, sDest, nTempIdx);
							tempKey.nOptional = atoi (sDest);
							m_KeyList.push_back (tempKey);
						}
						bPushShiftRelease = false;
						bPushAltRelease = false;
						bPushCtrlRelease = false;
						break;
					case Key_Delay:
						if (c == '>')
							tempKey.nOptional = 0;
						else
						{
							CString sDest;
							nTempIdx += GetKeyParam (m_sKeys, sDest, nTempIdx);
							tempKey.nOptional = atoi (sDest);
							m_KeyList.push_back (tempKey);
						}
						bPushShiftRelease = false;
						bPushAltRelease = false;
						bPushCtrlRelease = false;
						break;
					}
					if (nType != Key_NotFound)
						idx = nTempIdx;
					break;
				}
				else
				{
					szTemp [nOffset] = c;
					++nTempIdx;
					++nOffset;
				}
			}
			// Not found!
			if (nTempIdx >= nKeyLength || (nTempIdx >= nTempIdx + MAX_SK_LEN - 1))
				bNotASpecialKey = true;
		}
	}
        }*/
        #endregion
    }
}
